﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using JasLib.Interop.Win32;

namespace JasLib.Interop
{
    /// <summary>
    /// Base SafeHandle with convenience features like a NULL constant and empty constructor.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [DebuggerDisplay("{handle}")]
    public abstract class SafeJasLibHandleZeroIsInvalid<T> : SafeHandle
        where T : SafeJasLibHandleZeroIsInvalid<T>, new()
    {
        protected SafeJasLibHandleZeroIsInvalid(bool ownsHandle)
            : base(IntPtr.Zero, ownsHandle)
        {
        }

        public SafeJasLibHandleZeroIsInvalid()
            : this(true)
        {
        }

        /// <summary>
        /// Admittedly, this is vulnerable to its public methods like SetHandleAsInvalid.
        /// But it works for now.
        /// It just sucks there is no way of passing null to a P/Invoke method and having it default to zero or something.
        /// The CLR marshaler could figure that out with a safehandle default value attribute.
        /// </summary>
        public static readonly T NULL = new T();

        public override bool IsInvalid
        {
            get { return (handle == IntPtr.Zero); }
        }

        protected override bool ReleaseHandle()
        {
            return true;
        }
    }

    //new IntPtr(-1)
    public abstract class SafeJasLibHandleZeroOrMinusOneIsInvalid<T> : SafeJasLibHandleZeroIsInvalid<T>
        where T : SafeJasLibHandleZeroOrMinusOneIsInvalid<T>, new()
    {
        protected SafeJasLibHandleZeroOrMinusOneIsInvalid(bool ownsHandle)
            : base(ownsHandle)
        {
        }

        public SafeJasLibHandleZeroOrMinusOneIsInvalid()
            : this(true)
        {
        }

        public override bool IsInvalid
        {
            get { return (handle == IntPtr.Zero || handle == new IntPtr(-1)); }
        }
    }
}
